package br.com.toscano.contpedido.view;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.primefaces.event.SelectEvent;

import br.com.toscano.contpedido.business.ClienteBC;
import br.com.toscano.contpedido.business.PedidoBC;
import br.com.toscano.contpedido.business.ProdutoBC;
import br.com.toscano.contpedido.business.StatusPedidoBC;
import br.com.toscano.contpedido.constant.ConstantesMensagem;
import br.com.toscano.contpedido.domain.Cliente;
import br.com.toscano.contpedido.domain.ContextoUsuario;
import br.com.toscano.contpedido.domain.ObjetoAbstrato;
import br.com.toscano.contpedido.domain.Pedido;
import br.com.toscano.contpedido.domain.PedidoProduto;
import br.com.toscano.contpedido.domain.Produto;
import br.com.toscano.contpedido.domain.StatusPedido;
import br.com.toscano.contpedido.exception.DescricaoException;
import br.gov.frameworkdemoiselle.annotation.PreviousView;
import br.gov.frameworkdemoiselle.message.MessageContext;
import br.gov.frameworkdemoiselle.stereotype.ViewController;
import br.gov.frameworkdemoiselle.template.AbstractEditPageBean;
import br.gov.frameworkdemoiselle.transaction.Transactional;
import br.gov.frameworkdemoiselle.util.ResourceBundle;

@ViewController
@PreviousView("./pedido_list.jsf")
public class PedidoEditMB extends AbstractEditPageBean<Pedido, Long> {

	private static final long serialVersionUID = 1L;

	private Map<Produto,BigDecimal> checkMap = new HashMap<Produto,BigDecimal>();
	private List<Produto> items;
	
	private Integer posicao;
	
	private String exibeHistorico;

	@Inject
	private ResourceBundle bundle;
	
	private String fone;
	private String nomePesquisa;
	private List<Cliente> clientesPesquisados;

	public String getFone() {
		String foneSessao =  (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(ConstantesMensagem.FONE);
		if ((fone == null || "".equals(fone)) && foneSessao != null) {
			fone = foneSessao;
		}
		return fone;
	}
	public void setFone(String fone) {
		this.fone = fone;
	}
	public String getNomePesquisa() {
		return nomePesquisa;
	}
	public void setNomePesquisa(String nomePesquisa) {
		this.nomePesquisa = nomePesquisa;
	}
	public void setClientesPesquisados(List<Cliente> clientes) {
		this.clientesPesquisados = clientes;
	}
	public List<Cliente> getClientesPesquisados() {
		return this.clientesPesquisados;
	}
	private boolean veioSelecao;
	public void selecionaCliente() {
		HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();    
		if (request.getParameter("cliente") != null && !"".equals(request.getParameter("cliente")) && !"null".equals(request.getParameter("cliente"))) {
			setCliente(new Long(request.getParameter("cliente")));
			items = null;
			checkMap.clear();
			trocarCliente();
		}	
		veioSelecao = true;
	}
	

	public boolean isVeioSelecao() {
		return veioSelecao;
	}
	public void setVeioSelecao(boolean veioSelecao) {
		this.veioSelecao = veioSelecao;
	}
	public void digitarFone() {
		System.out.println(fone);
		clientesPesquisados = null;
	}

	public void pesquisarCliente() {
		if ((fone != null && !"".equals(fone)) || (nomePesquisa != null && !"".equals(nomePesquisa))) {

			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(ConstantesMensagem.FONE,  null);

			this.clientesPesquisados = clienteBC.pesquisarCliente(this.getFone(), this.getNomePesquisa());
		}
	}

	@Inject
	private MessageContext messageContext;

	@Inject
	private FacesContext facesContext;

	@Inject
	private PedidoBC pedidoBC;

	private List<SelectItem> horas;
	private List<SelectItem> minutos;
	

	public List<SelectItem> getHoras() {
		horas = new ArrayList<SelectItem>();
		for (int i = 23; i >= 0; i--) {
			String descricao = "" + i;
			if (i <= 9) {
				descricao = "0" + i;
			}
			horas.add(new SelectItem(i, descricao));
		}

		return horas;
	}
	public void setHoras(List<SelectItem> horas) {
		this.horas = horas;
	}
	public List<SelectItem> getMinutos() {
		minutos = new ArrayList<SelectItem>();
		for (int i = 60; i >= 0; i--) {
			String descricao = "" + i;
			if (i <= 9) {
				descricao = "0" + i;
			}
			minutos.add(new SelectItem(i, descricao));
		}

		return minutos;
	}
	public void setMinutos(List<SelectItem> minutos) {
		this.minutos = minutos;
	}


	
	@Inject
	private ClienteBC clienteBC;
	private List<SelectItem> clientes;
	private Long cliente;

	@Inject
	private ProdutoBC produtoBC;
	private List<SelectItem> produtos;
	private Long produto;

	@Inject
	private StatusPedidoBC statusPedidoBC;
	private List<SelectItem> statusPedidos;
	private Long statusPedido;

	public List<SelectItem> getStatusPedidos() {
		statusPedidos = new ArrayList<SelectItem>();
		if (this.getBean() == null || this.getBean().getId() == null) {
			StatusPedido obj = statusPedidoBC.load(StatusPedido.ENTREGUE);
			statusPedidos.add(new SelectItem(obj.getId(), obj.getDescricao()));
		} else {
			
			List<StatusPedido> lista = statusPedidoBC.findAll();
			for (StatusPedido obj: lista) {
				if (obj.getId().equals(this.getBean().getStatusPedido().getId()) || obj.getId().equals(StatusPedido.ENTREGUE) ) {
					statusPedidos.add(new SelectItem(obj.getId() , obj.getDescricao()));
				}
			}
		}
		return statusPedidos;
	}

	public void setStatusPedidos(List<SelectItem> statusPedidos) {
		this.statusPedidos = statusPedidos;
	}

	public Long getStatusPedido() {
		if(statusPedido == null && this.getBean().getStatusPedido() != null)
			statusPedido = this.getBean().getStatusPedido().getId();
		return statusPedido;
	}

	public void setStatusPedido(Long statusPedido) {
		this.statusPedido = statusPedido;
	}

	private BigDecimal quantidade;
	
	public List<SelectItem> getClientes() {
		clientes = new ArrayList<SelectItem>();
		if (veioSelecao && this.getCliente() != null && !this.getCliente().equals(0l)) {
			Cliente obj = this.clienteBC.load(this.getCliente());
			String desconto = "";
			if (obj.getDesconto() != null && !obj.getDesconto().setScale(2,BigDecimal.ROUND_UP).equals(BigDecimal.ZERO.setScale(2,BigDecimal.ROUND_UP))) {
				desconto = " (" + obj.getDesconto() + "%)";
			}
			clientes.add(new SelectItem(obj.getId() , obj.getNome() + desconto));
		} else {
			List<Cliente> lista = clienteBC.findAll();
			for (Cliente obj: lista) {
				String desconto = "";
				if (obj.getDesconto() != null && !obj.getDesconto().setScale(2,BigDecimal.ROUND_UP).equals(BigDecimal.ZERO.setScale(2,BigDecimal.ROUND_UP))) {
					desconto = " (" + obj.getDesconto() + "%)";
				}
				clientes.add(new SelectItem(obj.getId() , obj.getNome() + desconto));
			}
		}
		return clientes;
	}

	public void setClientes(List<SelectItem> clientes) {
		this.clientes = clientes;
	}

	public Long getCliente() {
		if(cliente == null && this.getBean().getCliente() != null)
			cliente = this.getBean().getCliente().getId();
		return cliente;
	}

	public void setCliente(Long cliente) {
		this.cliente = cliente;
	}

	public Integer getPosicao() {
		return posicao;
	}

	public void setPosicao(Integer posicao) {
		this.posicao = posicao;
	}

	public List<SelectItem> getProdutos() {
		produtos = new ArrayList<SelectItem>();
		List<Produto> lista = produtoBC.listarAtivos();
		for (Produto obj: lista) {
			produtos.add(new SelectItem(obj.getId() , obj.getUnidadeMedida().getSigla()  + " - " + obj.getDescricao()));
		}
		return produtos;
	}

	public void setProdutos(List<SelectItem> produtos) {
		this.produtos = produtos;
	}

	public Long getProduto() {
		return produto;
	}

	public void setProduto(Long produto) {
		this.produto = produto;
	}

	public BigDecimal getQuantidade() {
		return quantidade;
	}

	public void setQuantidade(BigDecimal quantidade) {
		this.quantidade = quantidade;
	}

	public void adicionarItem() {
		PedidoProduto item = new PedidoProduto();

		Produto produto = produtoBC.load(this.getProduto());

		item.setProduto(produto);
		item.setValorUnitario(produto.getValor());
		item.setPedido(this.getBean());
		item.setQuantidade(this.getQuantidade());
		item.setValorTotalItem(produto.getValor().multiply(this.getQuantidade()));

		if (this.getBean().getListaPedidoProduto() == null) {
			this.getBean().setListaPedidoProduto(new ArrayList<PedidoProduto>());
		}

		this.getBean().getListaPedidoProduto().add(item);
		
		somatorio();

		this.setProduto(null);
		this.setQuantidade(null);
	}

	private void somatorio() {
		BigDecimal somatorioValor = BigDecimal.ZERO;
		for(PedidoProduto pp : this.getBean().getListaPedidoProduto()) {
			somatorioValor = somatorioValor.add(pp.getValorTotalItem());
		}
		this.getBean().setValorTotalPedido(somatorioValor);
	}

	public void removerItem() {
		if (this.posicao != null) {
			this.getBean().getListaPedidoProduto().remove(this.posicao.intValue());
			somatorio();
		}
	}
	
	
	@Override
	@Transactional
	public String delete() {
		this.pedidoBC.delete(getId());
		return getPreviousView();
	}
	
	protected void clear() {
		super.clear();
	}
	
	public boolean montaObjeto() {
		
		if(!this.isUpdateMode()) {
			if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(ConstantesMensagem.CONTEXTO_USUARIO_SESSAO) != null) {
				ContextoUsuario contexto = (ContextoUsuario) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(ConstantesMensagem.CONTEXTO_USUARIO_SESSAO);
				this.getBean().setUsuario(contexto.getUsuario());
			}
		}

		if(this.getCliente() != null)
			this.getBean().setCliente(this.clienteBC.load(this.getCliente()));

		if(this.getStatusPedido() != null && this.isUpdateMode()) {
			this.getBean().setStatusPedido(this.statusPedidoBC.load(this.getStatusPedido()));
		} else {
			this.getBean().setStatusPedido(this.statusPedidoBC.load(StatusPedido.ENTREGUE));
		}
		
		Cliente cliente = null;
		if (this.getCliente() != null) {
			cliente = clienteBC.load(this.getCliente());
		}

		this.getBean().setListaPedidoProduto(new ArrayList<PedidoProduto>());
		Map<Produto, BigDecimal> map = getSelected();
		BigDecimal valorTotal = BigDecimal.ZERO;
		for (Produto p : map.keySet()) {

			if (!ObjetoAbstrato.DESATIVADO.equals(p.getAtivo())) {
				PedidoProduto pp = new PedidoProduto();
				pp.setPedido(this.getBean());
				pp.setProduto(p);
				pp.setQuantidade(map.get(p));
				pp.setValorUnitario(p.getValor());
				BigDecimal multiplicacao = pp.getValorUnitario().setScale(2,BigDecimal.ROUND_UP).multiply(pp.getQuantidade().setScale(2,BigDecimal.ROUND_UP)).setScale(2,BigDecimal.ROUND_UP); 
				if (cliente != null && cliente.getDesconto() != null && !cliente.getDesconto().equals(BigDecimal.ZERO)) {
					BigDecimal porcento = cliente.getDesconto().setScale(2,BigDecimal.ROUND_UP).divide(BigDecimal.TEN.multiply(BigDecimal.TEN)).setScale(2,BigDecimal.ROUND_UP);
					multiplicacao = multiplicacao.multiply(BigDecimal.ONE.subtract(porcento)).setScale(2,BigDecimal.ROUND_HALF_DOWN);
				}
				pp.setValorTotalItem(multiplicacao);
				valorTotal = valorTotal.add(pp.getValorTotalItem());
				this.getBean().getListaPedidoProduto().add(pp);
			}
		}
		
		this.getBean().setValorTotalPedido(valorTotal);
		
		List<PedidoProduto> lista = this.getBean().getListaPedidoProduto();		
		if(lista == null || lista.size() == 0) {
			facesContext.addMessage("listaProdutoPedido", new FacesMessage(bundle.getString("pedido.produto.obrigatorio")));
			return false;
		}

		return true;
	}

	public void calcularTotal() {
		BigDecimal valorTotal = BigDecimal.ZERO;

		Cliente cliente = null;
		if (this.getCliente() != null) {
			cliente = clienteBC.load(this.getCliente());
		}
		if (cliente != null) {
			Map<Produto, BigDecimal> map = getSelected();
			for (Produto p : map.keySet()) {
				if (!ObjetoAbstrato.DESATIVADO.equals(p.getAtivo())) {
					PedidoProduto pp = new PedidoProduto();
					pp.setPedido(this.getBean());
					pp.setProduto(p);
					pp.setQuantidade(map.get(p));
					pp.setValorUnitario(p.getValor());
					BigDecimal multiplicacao = pp.getValorUnitario().setScale(2,BigDecimal.ROUND_UP).multiply(pp.getQuantidade().setScale(2,BigDecimal.ROUND_UP)).setScale(2,BigDecimal.ROUND_UP); 
					if (cliente != null && cliente.getDesconto() != null && !cliente.getDesconto().equals(BigDecimal.ZERO)) {
						BigDecimal porcento = cliente.getDesconto().setScale(2,BigDecimal.ROUND_UP).divide(BigDecimal.TEN.multiply(BigDecimal.TEN)).setScale(2,BigDecimal.ROUND_UP);
						multiplicacao = multiplicacao.multiply(BigDecimal.ONE.subtract(porcento)).setScale(2,BigDecimal.ROUND_HALF_DOWN);
					}
					pp.setValorTotalItem(multiplicacao);
					valorTotal = valorTotal.add(pp.getValorTotalItem());
				}
			}
		}
		
		this.getBean().setValorTotalPedido(valorTotal);
	}	
	
	@Override
	@Transactional
	public String insert() {
		if (montaObjeto()) { 
			Pedido pedido =  this.pedidoBC.insert(getBean());

			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(ConstantesMensagem.FONE,  null);
			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("idPedidos", pedido.getId());

			return getPreviousView() + "?idPedido=" + pedido.getId();
		} else {
			return getCurrentView();
		}
	}
	
	@Override
	@Transactional
	public String update() {
		if (montaObjeto()) { 
			Pedido pedido =  this.pedidoBC.update(getBean());
			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(ConstantesMensagem.FONE,  null);
			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("idPedidos", pedido.getId());
			return getPreviousView() + "?idPedido=" + pedido.getId();
		} else {
			return getCurrentView();
		}
	}
	
	@Override
	protected Pedido handleLoad(Long pedido) {
		setBean(this.pedidoBC.load(pedido));
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("pedidos", null);
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("pedido", null);
		
		getItems();
		
		if(this.getBean() != null && this.getBean().getListaPedidoProduto() != null) {
			for (Produto pa : items) {
				for (PedidoProduto paCadastrado : this.getBean().getListaPedidoProduto()) {
					if (pa.getId().equals(paCadastrado.getProduto().getId())) {
						checkMap.put(pa, paCadastrado.getQuantidade());
					}
				}
				if (checkMap.get(pa) == null ) {
					checkMap.put(pa, BigDecimal.ZERO);
				}
			}
		}

		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("pedido", this.getBean());
		
		return this.getBean();
	}
	
	public void limparPedido() {
		checkMap.clear();
		for (Produto p : this.getItems()) {
			checkMap.put(p, BigDecimal.ZERO);
		}
		calcularTotal();
	}
	
	public void trocarCliente() {
		
		String exibeHistorico = (String)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("exibeHistorico");
		
		checkMap.clear();
		for (Produto p : this.getItems()) {
			checkMap.put(p, BigDecimal.ZERO);
		}
		this.getBean().setHora(12);
		this.getBean().setMinuto(0);
		
		if (exibeHistorico == null || (exibeHistorico != null && !exibeHistorico.equals("false"))) {
			Pedido pedido = pedidoBC.consultarUltimoPedidos(this.getCliente());
			if (pedido != null) {
				for (PedidoProduto pp : pedido.getListaPedidoProduto()) {
					checkMap.put(pp.getProduto(), pp.getQuantidade());
				}

				if (pedido.getHora() != null) {
					this.getBean().setHora(pedido.getHora());
				} else {
					this.getBean().setHora(12);
				}
				if (pedido.getMinuto() != null) {
					this.getBean().setMinuto(pedido.getMinuto());
				} else {
					this.getBean().setMinuto(0);
				}
			}
			calcularTotal();
		}
	}

	public List<Produto> getItems() {
		if (items == null && this.getCliente() != null) {
			items = this.produtoBC.listarAtivos();
		}
		return items;
	}

	public Map<Produto, BigDecimal> getCheckMap() {
		if (checkMap == null) {
			checkMap = new HashMap<Produto,BigDecimal>(); 
		}
		
		if (items == null ) {
			checkMap.clear();
		}

		if (checkMap != null && items != null) {
			for (Produto produto : getItems()) {
				if (!checkMap.containsKey(produto)) {
					checkMap.put(produto, BigDecimal.ZERO);
				}
			}
		}

		return checkMap;
	}

	public Map<Produto, BigDecimal> getSelected() {
		Map<Produto, BigDecimal> result = new HashMap<Produto, BigDecimal>();
	    for (Entry<Produto,BigDecimal> entry : checkMap.entrySet()) {

	    	if (entry.getValue() != null) {
	        	try {
	        		BigDecimal quantidade = new BigDecimal (entry.getValue() + "");
		        	if (quantidade.doubleValue() != 0d) {
		        		result.put(entry.getKey(), quantidade);
		        	}
				} catch (NumberFormatException e) {
//					facesContext.addMessage("listaProdutoPedido", new FacesMessage("Digite uma quantidade válida!"));
					throw new DescricaoException("Digite uma quantidade válida!");
				}
	        }
	    }
	    return result;
	}
	
	
	public void postProcessXLS(Object document) {
		
		HSSFWorkbook wb = (HSSFWorkbook) document;
		HSSFSheet sheet = wb.getSheetAt(0);

		
		CellStyle style = wb.createCellStyle();
		Font font = wb.createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
		style.setFont(font);
		style.setAlignment(CellStyle.ALIGN_RIGHT);
		
		Row totalRow = sheet.createRow(0);
		Cell cell1 = totalRow.createCell(0);
		cell1.setCellValue("Código Pedido");
		cell1.setCellStyle(style);
		Cell cell2 = totalRow.createCell(1);
		cell1.setCellValue(""+this.getBean().getId());

		
		/******************** HEADER **********************/		
		CellStyle headerStyle = wb.createCellStyle();
		Font headerFont = wb.createFont();
		headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
		headerFont.setColor(HSSFColor.BLUE.index);
		headerStyle.setFont(headerFont);
		headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
		 
		Row headerRow = sheet.getRow(0);
		int cont = 0; 
		for (Cell cell : headerRow) {
			cell.setCellStyle(headerStyle);
			if (0 == cont) {
				cell.setCellValue("Produto");
			} else if (cont ==1) {
				cell.setCellValue("Valor");
			} else if (cont ==1) {
				cell.setCellValue("Quantidade");
			}
			cont++;
		}
		
		/******************** TOTAL **********************/
		style = wb.createCellStyle();
		font = wb.createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//		font.setColor(HSSFColor.ORANGE.index); 
		style.setFont(font);
		style.setAlignment(CellStyle.ALIGN_RIGHT);
		totalRow = sheet.createRow(sheet.getLastRowNum()+2);

		cell1 = totalRow.createCell(0);

		cell1.setCellValue("Total");
		cell1.setCellStyle(style);
		cell2 = totalRow.createCell(1);
		
		BigDecimal valor = BigDecimal.ZERO;
		List<PedidoProduto> pedidos = this.getBean().getListaPedidoProduto();
		for (PedidoProduto pedido : pedidos) {
			valor = valor.add(pedido.getValorTotalItem());
		}
		
		cell2.setCellFormula(valor.toString());
		cell2.setCellStyle(style);

		//Ajuste do tamanho das colunas
		sheet.autoSizeColumn(0);
		sheet.autoSizeColumn(1);
	}
	
	public void salvaDados() {
		System.out.println("thiago");
	}

	public void dateChange(AjaxBehaviorEvent event)  {
		System.out.println("thiago2");
	}
	
	public void limpiaLink(SelectEvent event) {
	    Date date = (Date) event.getObject();
	    System.out.print(date.toString());
	}
	
	public String getExibeHistorico() {
		return exibeHistorico;
	}
	public void setExibeHistorico(String exibeHistorico) {
		this.exibeHistorico = exibeHistorico;
		System.out.println("setExibeHistorico: " + this.exibeHistorico);
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("exibeHistorico", exibeHistorico);
	}
	public void comHistorico() {
		setExibeHistorico("true");
	}
	public void semHistorico() {
		setExibeHistorico("false");
	}
	
	
	public boolean habilitaBotaoUpdate() {

		boolean retorno = false;
		
		ContextoUsuario usuario = (ContextoUsuario)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(ConstantesMensagem.CONTEXTO_USUARIO_SESSAO);
		if (usuario != null && usuario.getUsuario().getIndicadorAlterarPedido().equals(ObjetoAbstrato.SIM)) {
			retorno = true;
		}
		
//		
//		if (isUpdateMode()) {
//			Calendar cal = Calendar.getInstance();
//			cal.setTime(new Date());
//			cal.set(Calendar.HOUR_OF_DAY,0);
//			cal.set(Calendar.MINUTE,0);
//			cal.set(Calendar.SECOND,0);
//			Date corrente = cal.getTime();
//
//			Calendar cal2 = Calendar.getInstance();
//			cal2.setTime(this.getBean().getDataEntrega());
//			cal2.set(Calendar.HOUR_OF_DAY,0);
//			cal2.set(Calendar.MINUTE,0);
//			cal2.set(Calendar.SECOND,0);
//			Date dataEntrega = cal2.getTime();
//
//			retorno = this.getBean().getProduzido().equals(Pedido.NAO) && corrente.getTime() <= dataEntrega.getTime();
//		}

		return retorno;
	}
}